import { rm } from 'fs/promises';
import { existsSync } from 'node:fs';
import path from 'path';
import { replaceSrcWithBuildInRecord, copyDir, PackageDir } from '../utils/utils.js';
import { color } from '../../core/color.js';
import { compilerLogger } from '../utils/loggers.js';
import { Compiler, traverse, transform } from '../utils/compiler.js';
import { getTypeScriptCompilerOptions } from './typescript.js';

const SeedDir = path.join(process.cwd(), "seed");
const SeedBuildDir = path.join(process.cwd(), ".robo", "seed");
async function buildSeed() {
  const startTime = Date.now();
  compilerLogger.debug(`Cleaning previous seed...`);
  await rm(SeedBuildDir, { recursive: true, force: true });
  if (!existsSync(SeedDir)) {
    compilerLogger.debug(`No seed directory found, skipping...`);
    return {
      time: 0
    };
  }
  if (Compiler.isTypescriptProject()) {
    compilerLogger.debug(`Compiling TypeScript files from ${SeedDir} to ${SeedBuildDir}...`);
    const tsOptions = await getTypeScriptCompilerOptions();
    const baseUrl = tsOptions.baseUrl ?? process.cwd();
    const compileOptions = {
      baseUrl,
      paths: replaceSrcWithBuildInRecord(tsOptions.paths ?? {})
    };
    compilerLogger.debug(`Compiler options:`, compileOptions);
    await traverse(SeedDir, SeedBuildDir, compileOptions, tsOptions, transform);
    await rm(path.join(process.cwd(), ".swc"), { recursive: true, force: true });
  } else {
    compilerLogger.warn("We recommend using TypeScript for your seed files.");
  }
  compilerLogger.debug(`Copying seed into Robo build...`);
  await copyDir(SeedDir, SeedBuildDir, [], []);
  compilerLogger.debug(`Successfully built seed in ${Date.now() - startTime}ms`);
  return {
    time: Date.now() - startTime
  };
}
function hasSeed(packageName) {
  const base = packageName.startsWith(".") ? process.cwd() : path.join(PackageDir, "..");
  const seedPath = path.resolve(base, packageName, ".robo", "seed");
  const fallbackPath = path.resolve(process.cwd(), "node_modules", packageName, ".robo", "seed");
  compilerLogger.debug(`Checking for ${packageName} seed files:`, seedPath, "or", fallbackPath);
  return existsSync(seedPath) || existsSync(fallbackPath);
}
async function useSeed(packageName) {
  compilerLogger.debug(`Looking for seed files in plugin ${color.bold(packageName)}...`);
  const base = packageName.startsWith(".") ? process.cwd() : path.join(PackageDir, "..");
  const fallbackPath = path.resolve(process.cwd(), "node_modules", packageName, ".robo", "seed");
  const projectSrc = path.join(process.cwd(), "src");
  let seedPath = path.resolve(base, packageName, ".robo", "seed");
  compilerLogger.debug("Looking in seed path:", seedPath, "or", fallbackPath);
  if (!existsSync(seedPath)) {
    seedPath = fallbackPath;
  }
  if (existsSync(seedPath)) {
    compilerLogger.debug("Seed folder exists! Verifying manifest...");
    const manifest = await Compiler.useManifest({
      basePath: path.resolve(seedPath, "..", ".."),
      name: packageName
    });
    const isTypeScript = manifest.__robo.language === "typescript";
    const excludeExts = Compiler.isTypescriptProject() && isTypeScript ? [".js", ".jsx"] : [".ts", ".tsx"];
    await copyDir(seedPath, projectSrc, excludeExts, [path.join(seedPath, "_root")], false);
    compilerLogger.debug(`Successfully copied seed files from`, color.bold(packageName));
    const rootPath = path.join(seedPath, "_root");
    if (existsSync(rootPath)) {
      compilerLogger.debug("Copying root seed files...");
      await copyDir(rootPath, process.cwd(), [], [], false);
      compilerLogger.debug(`Successfully copied root seed files from`, color.bold(packageName));
    }
  }
}

export { buildSeed, hasSeed, useSeed };
